/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bizentity.webapi;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.bef.bemanager.befdtconsistencycheckevent.BefDtConsistencyCheckEventBroker;
import com.inspur.edp.bef.bemanager.dependency.ManageProjectDependencyUtil;
import com.inspur.edp.bef.bemanager.dependency.MavenDependency;
import com.inspur.edp.bef.bemanager.rtmodule.RuntimeModuleUtil;
import com.inspur.edp.bef.bemanager.util.BefFileUtil;
import com.inspur.edp.bef.bemanager.validate.model.BizEntityChecker;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.actioneventargs.ChangingActionCodeEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.actioneventargs.ChangingActionParamsEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.actioneventargs.ChangingActionReturnEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.actioneventargs.DeletingActionEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.entityeventargs.ChangingEntityCodeEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.entityeventargs.RemovingEntityEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.fieldeventargs.ChangingFieldDataTypeEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.fieldeventargs.ChangingFieldLabelIdEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.fieldeventargs.ChangingFieldObjectTypeEventArgs;
import com.inspur.edp.bef.bizentity.dtconsistencycheck.fieldeventargs.RemovingFieldEventArgs;
import com.inspur.edp.bef.bizentity.gspbusinessentity.api.IGspBeExtendInfoService;
import com.inspur.edp.bef.bizentity.gspbusinessentity.entity.GspBeExtendInfo;
import com.inspur.edp.bef.bizentity.gspbusinessentitylabel.api.IGspBeLabelInfoService;
import com.inspur.edp.bef.bizentity.gspbusinessentitylabel.entity.GspBeLabelInfo;
import com.inspur.edp.bef.bemanager.expression.entity.ExpressionSchema;
import com.inspur.edp.bef.bemanager.expression.BefExpressionAdapter;
import com.inspur.edp.cef.designtime.api.dtconsistencycheck.ConsistencyCheckEventMessage;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.das.commonmodel.util.HandleAssemblyNameUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataRTService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationService;
import com.inspur.lcm.metadata.logging.LoggerDisruptorQueue;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.activation.DataHandler;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
//import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;

@Path("")
@Produces(MediaType.APPLICATION_JSON)
public class BeCodeGenController {

    @Autowired
    private IGspBeExtendInfoService beExtendInfoService;
    @Autowired
    private IGspBeLabelInfoService beLabelInfoServicee;

    /**
     * 根据id获取一条标签信息
     *
     * @return
     */
    @Path("beLabelInfo")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GspBeLabelInfo getBeLabelInfo(@QueryParam("id") String id) {
        return this.beLabelInfoServicee.getBeLabelInfo(id);
    }

    /**
     * 获取所有标签信息
     *
     * @return
     */
    @Path("beLabelInfos")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<GspBeLabelInfo> getBeLabelInfos() {
        return this.beLabelInfoServicee.getBeLabelInfos();
    }

    /**
     * 保存标签配置列表
     *
     *
     * @param infos 标签信息
     * @return
     */
    @Path("beLabelInfos")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void saveBeLabelInfos(List<GspBeLabelInfo> infos) {
        this.beLabelInfoServicee.saveBeLabelInfos(infos);
    }

    /**
     * 获取所有扩展配置
     *
     * @param id 业务实体id
     * @return
     */
    @Path("beExtendInfo")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GspBeExtendInfo getExtendConfigById(@QueryParam("id") String id) {
        return this.beExtendInfoService.getBeExtendInfo(id);
    }

    /**
     * 获取所有扩展配置
     *
     * @return
     */
    @Path("beExtendInfo/configId")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GspBeExtendInfo getExtendConfigByConfigId(@QueryParam("configId") String configId) {
        return this.beExtendInfoService.getBeExtendInfoByConfigId(configId);
    }

    /**
     * 获取所有扩展配置
     *
     * @return
     */
    @Path("beExtendInfos")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<GspBeExtendInfo> getExtendConfigs() {
        return this.beExtendInfoService.getBeExtendInfos();
    }

    /**
     * 保存扩展配置列表
     *
     * @return
     */
    @Path("beExtendInfos")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void saveExtendConfigs(List<GspBeExtendInfo> infos) {
        this.beExtendInfoService.saveGspBeExtendInfos(infos);
    }


  /**
   * 删除节点
   */
  @Path("befDtConsistencyCheck/removingEntity")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public RemovingEntityEventArgs removingEntity(RemovingEntityEventArgs args) {
    BefDtConsistencyCheckEventBroker beEventBroker = SpringBeanUtils
        .getBean(BefDtConsistencyCheckEventBroker.class);
    beEventBroker.fireRemovingEntity(args);

    if(args.eventMessages.size() != 0){
      BefConsistencyCheckMessage(args.eventMessages, "请先解除该BE节点的依赖和关联信息");
    }
    return args;
  }


  /**
   * 删除字段
   */
  @Path("befDtConsistencyCheck/removingField")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public RemovingFieldEventArgs removingField(RemovingFieldEventArgs args) {
    BefDtConsistencyCheckEventBroker beEventBroker = SpringBeanUtils
        .getBean(BefDtConsistencyCheckEventBroker.class);
    beEventBroker.fireRemovingField(args);
    if(args.eventMessages.size() != 0){
      BefConsistencyCheckMessage(args.eventMessages, "请先解除该BE字段的依赖和关联信息");
    }
    return args;
  }


  /**
   * 删除动作
   */
  @Path("befDtConsistencyCheck/deletingAction")
  @PUT
  @Produces(MediaType.APPLICATION_JSON)
  public DeletingActionEventArgs deletingAction(DeletingActionEventArgs args) {
    BefDtConsistencyCheckEventBroker beEventBroker = SpringBeanUtils
        .getBean(BefDtConsistencyCheckEventBroker.class);
    beEventBroker.fireDeletingAction(args);


    if(args.eventMessages.size() != 0){
      BefConsistencyCheckMessage(args.eventMessages, "请先解除该动作的依赖信息");
    }
    return args;
  }

    /**
     * 运行时生成
     *
     * @param metadataProjectPath 元数据工程路径
     */
    @Path("rtgenerate")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public void addRTModule(@QueryParam("path") String metadataProjectPath) {
        RuntimeModuleUtil util = RuntimeModuleUtil.getInstance();
        util.rtGenerate(metadataProjectPath);
    }

    /**
     * 添加默认maven引用
     *
     * @param metaProjectPath
     */
    @Path("handleProjectDependency")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public void handleProjectDependency(@QueryParam("path") String metaProjectPath) {
        ManageProjectDependencyUtil util = ManageProjectDependencyUtil.getInstance();
        util.addDefaultProjectDependency(BefFileUtil.getJavaProjPath(metaProjectPath));
    }

    /**
     * 添加默认maven引用
     *
     * @param javaProjectPath
     * @param jarPath         jar包所在路径
     * @param dependencyJson  dependency列表json
     */
    @Path("installCustomProjectDependency")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void installCustomProjectDependency(@QueryParam("javaProjectPath") String javaProjectPath,
                                               @QueryParam("jarPath") String jarPath, String dependencyJson) {
        ManageProjectDependencyUtil util = ManageProjectDependencyUtil.getInstance();
        if (dependencyJson == null) {
            return;
        }
        ArrayList<MavenDependency> dependencies = new ArrayList<MavenDependency>();
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode node = mapper.readTree(dependencyJson);
            for (JsonNode item : node) {
                dependencies.add(mapper.readValue(item.toString(), MavenDependency.class));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        util.addProjectDependency(javaProjectPath, jarPath, dependencies);
    }

    @Path("loadMetadata")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String loadMetadata(@QueryParam("relativePath") String relativePath,
                               @QueryParam("fileName") String fileName) throws JsonProcessingException {
        MetadataService service = SpringBeanUtils.getBean(MetadataService.class);
        GspMetadata metadata = service.loadMetadata(fileName, relativePath);
        return new ObjectMapper().writeValueAsString(metadata.getHeader());
    }

    @Path("handledBeMeta")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String loadMetadata(@QueryParam("beId") String beId) throws JsonProcessingException {
      GspBusinessEntity sourceBe = loadBe(beId);
      GspBusinessEntity beAfaterToCamel = convertToCamel(sourceBe);
        GspMetadata newMeta = new GspMetadata();
      newMeta.setContent(beAfaterToCamel);
        return new ObjectMapper().writeValueAsString(newMeta);
    }

  private GspBusinessEntity loadBe(String beId) {
    if (beId == null || beId.isEmpty()) {
      throw new RuntimeException("请传入有效beId.");
    }
    MetadataRTService service = (MetadataRTService) SpringBeanUtils
        .getBean(MetadataRTService.class);
    GspMetadata meta = service.getMetadata(beId);
    if (meta == null) {
      meta = MetadataUtil.getCustomMetadata(beId);
    }
    if (meta == null) {
      throw new RuntimeException("根据BeID'" + beId + "'，使用CustomizationService未获取到元数据定义");
    }
    GspBusinessEntity be = ((GspBusinessEntity) meta.getContent()).clone();
    if (be == null) {
      throw new RuntimeException("根据BeID'" + beId + "'，加载出的BE元数据为空。");
    }
    return be;
  }

  private GspBusinessEntity convertToCamel(GspBusinessEntity sourceBe) {
    GspBusinessEntity commonModel = (GspBusinessEntity) sourceBe.convertToCamelCaseProperty();
    // 所有节点编号camel
    commonModel.getAllObjectList().forEach(object -> {
      if (object.getObjectType() == GspCommonObjectType.ChildObject) {
        object.setCode(StringUtils.toCamelCase(object.getCode()));
      }
    });
    return commonModel;
  }

  @Path("expression")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public String getExpression(@QueryParam("beId") String beId) throws JsonProcessingException {
    GspBusinessEntity sourceBe = loadBe(beId);
    GspBusinessEntity beAfaterToCamel = convertToCamel(sourceBe);
    // 调用Exception方法
    BefExpressionAdapter expressionAdapter = new BefExpressionAdapter();
    ExpressionSchema schema = expressionAdapter.convertCommonModel(beAfaterToCamel);
    return new ObjectMapper().writeValueAsString(schema);
  }

    @Path("generatedConfigId")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getGeneratedConfigId(@QueryParam("generatingAssembly") String generatingAssembly)
            throws JsonProcessingException {
        if (generatingAssembly == null || generatingAssembly.isEmpty()) {
            return "";
        }
        return new ObjectMapper()
                .writeValueAsString(HandleAssemblyNameUtil.convertToJavaPackageName(generatingAssembly));
    }

    @Path("checkbe")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public void checkKeywords(String jsonObject) {
        if (jsonObject == null || jsonObject.isEmpty()) {
            throw new RuntimeException("请传入有效Json对象.");
        }
        ObjectMapper mapper = new ObjectMapper();
        GspBusinessEntity businessEntity = null;
        try {
            businessEntity = mapper.readValue(jsonObject, GspBusinessEntity.class);
        } catch (JsonProcessingException e) {
           throw new RuntimeException(e);
        }
        BizEntityChecker.getInstance().check(businessEntity);
    }
    /**
     * 控制台输出BEF Warnings
     *
     * @param messages
     */
    protected void BefConsistencyCheckMessage(List<ConsistencyCheckEventMessage> messages,String
            suffix){
        StringBuilder befWarnings = new StringBuilder();
        if (messages.size() > 0)
            messages.forEach(message->{
                befWarnings.append(message.message);
            });
        befWarnings.append(suffix);
        String currentUerId = CAFContext.current.getUserId();
        if(currentUerId == null || currentUerId.equals("")) {
            throw new RuntimeException("获取当前用户ID为空");
        }
        LoggerDisruptorQueue.publishEvent("[BEF Warning]:" + befWarnings.toString(),currentUerId);
    }
}
